﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PasswordGenerator
{
    abstract internal class PasswordGenerationStrategy
    {
        abstract internal void Init(List<PasswordRequirement> reqs);
        abstract internal string GeneratePassword();
    }

    internal class DefaultStrategy : PasswordGenerationStrategy
    {
        private static Random random = new Random();
        PasswordProfile profile;

        internal override void Init(List<PasswordRequirement> reqs)
        {
            profile = new PasswordProfile(reqs);
        }

        internal override string GeneratePassword()
        {
            if (profile.Requirements.Count == 0)
                return string.Empty;

            int randomRequirement = 0;

            while (profile.Password.Length < profile.MAXIMUM_LENGTH)
            {
                PasswordRequirement characterNeeded = null;

                if (profile.Password.Length >= profile.MINIMUM_LENGTH)
                {
                    CheckPassword(profile, ref characterNeeded);
                }
                else
                {
                    randomRequirement = random.Next(0, profile.Requirements.Count);
                    characterNeeded = profile.Requirements[randomRequirement];
                }

                if (profile.RequirementFullfilled)
                    return profile.Password;

                FullFillRequirements(profile, characterNeeded);
            }

            return profile.Password;
        }

        private static void CheckPassword(PasswordProfile profile, ref PasswordRequirement characterNeeded)
        {
            foreach (PasswordRequirement req in profile.Requirements)
            {
                if (req.Count == 0)
                {
                    characterNeeded = req; // (PasswordRequirement)Activator.CreateInstance(req.GetType());
                    break;
                }
            }

            if (characterNeeded == null)
                profile.RequirementFullfilled = true;
        }

        private static void FullFillRequirements(PasswordProfile profile, PasswordRequirement characterNeeded)
        {
            int randomNumber = 0;
            int randomRange = 0;

            randomRange = random.Next(0, characterNeeded.profile.CharacterRange.Count);
            ASCIIRange temp = characterNeeded.profile.CharacterRange[randomRange];

            randomNumber = random.Next(temp.Start, temp.End + 1);

            profile.Password += (char)randomNumber;
            characterNeeded.Count++;
        }
    }
}
